package com.ywd.platform.netty.jt080.po;

/**
 * 车辆状态标志枚举
 * 基于JT/T808协议标准定义状态位
 */
public enum StatusFlag {
    // 低位状态标志 (0-15)
    ACC_STATUS(0, "ACC状态"),
    POSITIONED_STATUS(1, "定位状态"),
    NORTH_LATITUDE(2, "北纬"),
    EAST_LONGITUDE(3, "东经"),
    OPERATIONAL_STATUS(4, "运营状态"),
    UNENCRYPTED_COORDINATES(5, "经纬度未经保密插件加密"),

    // 保留位 6-7
    RESERVED_6(6, "保留位6"),
    RESERVED_7(7, "保留位7"),

    // 车厢状态："空车", "半载", "保留", "满载" (使用两位表示)
    CARRIAGE_STATUS(8, 2, "车厢状态", new String[]{"空车", "半载", "保留", "满载"}),

    // 车辆系统状态
    FUEL_SYSTEM_STATUS(10, "车辆油路状态"),
    ELECTRICAL_SYSTEM_STATUS(11, "车辆电路状态"),
    DOORS_STATUS(12, "车门状态"),

    // 车门状态
    DOOR1_STATUS(13, "门1状态"),
    DOOR2_STATUS(14, "门2状态"),
    DOOR3_STATUS(15, "门3状态"),
    DOOR4_STATUS(16, "门4状态"),
    DOOR5_STATUS(17, "门5状态"),

    // 卫星定位系统状态
    GPS_USED_STATUS(18, "使用GPS卫星进行定位"),
    BEIDOU_USED_STATUS(19, "使用北斗卫星进行定位"),
    GLONASS_USED_STATUS(20, "使用GLONASS卫星进行定位"),
    GALILEO_USED_STATUS(21, "使用Galileo卫星进行定位"),

    // 车辆状态
    VEHICLE_STATUS(22, "车辆状态"),

    // 保留位 23-31
    RESERVED_23(23, "保留位23"),
    RESERVED_24(24, "保留位24"),
    RESERVED_25(25, "保留位25"),
    RESERVED_26(26, "保留位26"),
    RESERVED_27(27, "保留位27"),
    RESERVED_28(28, "保留位28"),
    RESERVED_29(29, "保留位29"),
    RESERVED_30(30, "保留位30"),
    RESERVED_31(31, "保留位31");

    private final int bitPosition;
    private final int bitLength;
    private final String description;
    private final String[] valueDescriptions;
    private final long bitMask;

    // 单比特状态构造函数
    StatusFlag(int bitPosition, String description) {
        this(bitPosition, 1, description, null);
    }

    // 多比特状态构造函数
    StatusFlag(int bitPosition, int bitLength, String description, String[] valueDescriptions) {
        this.bitPosition = bitPosition;
        this.bitLength = bitLength;
        this.description = description;
        this.valueDescriptions = valueDescriptions;

        // 计算位掩码
        if (bitLength == 1) {
            this.bitMask = 1L << bitPosition;
        } else {
            long mask = 0;
            for (int i = 0; i < bitLength; i++) {
                mask |= 1L << (bitPosition + i);
            }
            this.bitMask = mask;
        }
    }

    public int getBitPosition() {
        return bitPosition;
    }

    public int getBitLength() {
        return bitLength;
    }

    public long getBitMask() {
        return bitMask;
    }

    public String getDescription() {
        return description;
    }

    public String[] getValueDescriptions() {
        return valueDescriptions;
    }

    /**
     * 检查给定的状态位掩码中是否包含当前状态
     */
    public boolean isSetIn(long statusBits) {
        if (bitLength == 1) {
            return (statusBits & bitMask) != 0;
        }
        // 对于多比特状态，需要提取对应的值
        long value = (statusBits & bitMask) >> bitPosition;
        return value != 0;
    }

    /**
     * 获取多比特状态的值描述
     */
    public String getValueDescription(long statusBits) {
        if (valueDescriptions == null || valueDescriptions.length == 0) {
            return description + ": " + isSetIn(statusBits);
        }

        long value = (statusBits & bitMask) >> bitPosition;
        if (value >= 0 && value < valueDescriptions.length) {
            return description + ": " + valueDescriptions[(int) value];
        }

        return description + ": 未知值(" + value + ")";
    }

    /**
     * 根据位位置获取状态标志
     */
    public static StatusFlag getByBitPosition(int bitPosition) {
        for (StatusFlag flag : values()) {
            if (flag.bitPosition <= bitPosition &&
                    bitPosition < flag.bitPosition + flag.bitLength) {
                return flag;
            }
        }
        return null;
    }

    /**
     * 解析状态位掩码，返回所有状态的描述
     */
    public static String parseStatusBits(long statusBits) {
        StringBuilder sb = new StringBuilder();
        for (StatusFlag flag : values()) {
            if (flag.bitLength == 1) {
                if (flag.isSetIn(statusBits)) {
                    sb.append(flag.getDescription()).append("\n");
                }
            } else {
                sb.append(flag.getValueDescription(statusBits)).append("\n");
            }
        }
        return sb.toString();
    }
}